package com.coovane.bytetrix.handler;

import com.coovane.bytetrix.common.enumeration.ErrorCodeEnum;
import com.coovane.bytetrix.common.exception.DuplicateException;
import com.coovane.bytetrix.common.exception.GenericException;
import com.coovane.bytetrix.common.exception.ParamIsNullException;
import com.coovane.bytetrix.common.response.GenericResult;
import com.mysql.cj.jdbc.exceptions.CommunicationsException;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

import javax.naming.SizeLimitExceededException;
import java.util.Objects;

/**
 * <p>
 * 全局异常处理
 * </p>
 *
 * @author: Hsu
 * @date: 2022/1/15 21:12
 * @copyright: companyName
 * @see
 * @since 1.8
 */
@RestControllerAdvice
@Slf4j(topic = "统一异常处理")
public class GlobalExceptionHandler {

    @Value("${spring.servlet.multipart.max-file-size:100MB}")
    private String MAX_FILE_SIZE;

    @Value("${spring.servlet.multipart.max-request-size:100MB}")
    private String MAX_REQUEST_SIZE;

    /**
     * IllegalArgumentException
     * 顶级的Exception 如果没有捕获到具体的异常 会由此异常处理器处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = IllegalArgumentException.class)
    public GenericResult<String> illegalArgumentExceptionHandler(IllegalArgumentException exception) {
        log.error("{}", exception.getMessage(), exception);
        return GenericResult.fail(ErrorCodeEnum.ILLEGAL_ARGUMENT.getErrorCode(), exception.getMessage());
    }

    /**
     * MultipartException
     * 顶级的Exception 如果没有捕获到具体的异常 会由此异常处理器处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = MultipartException.class)
    public GenericResult<String> multipartExceptionHandler(MultipartException exception) {
        log.error("{}", exception.getMessage(), exception);
        String message;
        if (exception.getRootCause() instanceof FileSizeLimitExceededException) {
            message = "上传文件过大[单个文件大小不得超过" + MAX_FILE_SIZE + "]";
        } else if (exception.getRootCause() instanceof SizeLimitExceededException) {
            message = "上传文件过大[总上传大小不得超过" + MAX_REQUEST_SIZE + "]";
        } else {
            message = "文件上传失败[服务器异常]";
        }
        return GenericResult.fail(ErrorCodeEnum.SIZE_LIMIT_EXCEEDED.getErrorCode(), message);
    }

    /**
     * BindException
     * 处理@NotNull和@NotBlank返回信息
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    public GenericResult<String> bindExceptionHandler(BindException exception) {
        log.error("{}", exception.getMessage(), exception);
        BindingResult bindingResult = exception.getBindingResult();
        // 这个是作用在字段上的校验才不会为null
        FieldError fieldError = bindingResult.getFieldError();
        return GenericResult.fail(ErrorCodeEnum.FIELD_BIND_ERROR.getErrorCode(), Objects.nonNull(fieldError) ? fieldError.getDefaultMessage() : bindingResult.getAllErrors().get(0).getDefaultMessage());
    }

    /**
     * 测试没有生效，可能是包扫码的问题
     * CommunicationsException
     * 处理数据库连接失败
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = CommunicationsException.class)
    public GenericResult<String> CommunicationsExceptionHandler(CommunicationsException exception) {
        log.error("{}", exception.getMessage(), exception);
        return GenericResult.fail(ErrorCodeEnum.LINK_FAILURE.getErrorCode(), ErrorCodeEnum.LINK_FAILURE.getErrorMsg());
    }

    /**
     * GenericException
     * 顶级的Exception 如果没有捕获到具体的异常 会由此异常处理器处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = GenericException.class)
    public GenericResult<String> genericExceptionHandler(GenericException exception) {
        log.error("{}", exception.getMessage(), exception);
        return GenericResult.fail(exception.getErrorCodeEnum().getErrorCode(), exception.getMessage());
    }

    /**
     * DuplicateException
     * 顶级的Exception 如果没有捕获到具体的异常 会由此异常处理器处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = DuplicateException.class)
    public GenericResult<String> duplicateExceptionHandler(DuplicateException exception) {
        log.error("{}", exception.getMessage(), exception);
        return GenericResult.fail(exception.getErrorCodeEnum().getErrorCode(), exception.getMessage());
    }

    /**
     * ParamIsNullException
     * 顶级的Exception 如果没有捕获到具体的异常 会由此异常处理器处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(value = ParamIsNullException.class)
    public GenericResult<String> paramIsNullExceptionHandler(ParamIsNullException exception) {
        log.error("{}", exception.getMessage(), exception);
        return GenericResult.fail(exception.getErrorCodeEnum().getErrorCode(), exception.getMessage());
    }

}
